/* 
原型模式(clone)，通过拷贝的方式创建新的对象，新的对象包含全部或者部分原来对象的内容。

本例：一个完整的医学图像数据，包括数据部分和数据信息部分(如图像分辨率、尺寸、偏移量和旋转矩阵等)。有些算法
在运行的过程中会对输入的数据内存进行修改，或者需要创建一个和数据一样大小的空间且数据信息一致，这种情况
就可以采用原型模式.
*/

#include <cstring>
#include <iostream>
#include <memory>
#include <vector>

using namespace std;

class Clone
{
public:
    virtual Clone* clone() = 0;
    virtual Clone* clone_blank() = 0;
    virtual void print_info()=0;
    virtual ~Clone(){};
};

class Volume: public Clone
{
public:
    Volume(){
        memset(&m_size, 0, sizeof(m_size));
        memset(&m_spacing, 0.0, sizeof(m_spacing));
        memset(&m_offset, 0.0, sizeof(m_offset));
        m_data = nullptr;
    }

    Volume(int* data, unsigned int* size, float* spacing, float* offset){
        for(size_t i = 0; i < 3; ++i){
            m_size[i] = size[i];
            m_spacing[i] = spacing[i];
            m_offset[i] = offset[i];
        }

        m_data = (int*)malloc(get_bytes_size());
        memcpy(m_data, data, get_bytes_size());
    }

    // 关键函数，拷贝构造函数
    Volume(const Volume& volume, bool copy_data){
        for(size_t i = 0; i < 3; ++i){
            this->m_size[i] = volume.m_size[i];
            this->m_offset[i] = volume.m_offset[i];
            this->m_spacing[i] = volume.m_spacing[i];
        }

        this->m_data = (int*)malloc(get_bytes_size());
        if(copy_data){
            memcpy(this->m_data, volume.m_data, this->get_bytes_size());
        }
        else{
            memset(this->m_data, 0, this->get_bytes_size());
        }
    }
    
    // 关键函数，调用拷贝构造函数
    Clone* clone(){
        return new Volume(*this, true);
    }

    // 关键函数，调用拷贝构造函数
    Clone* clone_blank(){
        return new Volume(*this, false);
    }

    void print_info(){
        cout<<"The size of volume: ["<< m_size[0] <<","<< m_size[1]<<","<<m_size[2]<<"]"<<endl;
        cout<<"The spacing of volume: ["<<m_spacing[0]<<","<<m_spacing[1]<<","<<m_spacing[2]<<"]"<<endl;
        cout<<"The offset of volume:["<<m_offset[0]<<","<<m_offset[1]<<","<<m_offset[2]<<"]"<<endl;

    }

    inline int get_bytes_size(){
        return static_cast<int>(m_size[0] * m_size[1] * m_size[2] * sizeof(int));
    }

    virtual ~Volume(){
        if (m_data){
            free(m_data);
        }
        
    };

private:
    int* m_data;
    unsigned int m_size[3];
    float m_spacing[3];
    float m_offset[3];
};


#pragma region //测试代码
int main(int argc, char const *argv[])
{
    unsigned int t_size[3] = {2, 3, 4};
    float t_offset[3] = {-100.0, 0.0, 100.0};
    float t_spacing[3] = {0.5, 1.0 ,1.5};
    vector<int> t_data(t_size[0] * t_size[1] * t_size[2], 10);

    int* a_data = (int*)malloc(20);
    
    unique_ptr<Clone> volume_ptr(new Volume(t_data.data(), t_size, t_spacing, t_offset));
    volume_ptr->print_info();

    unique_ptr<Clone> clone_ptr(volume_ptr->clone());
    clone_ptr->print_info();

    free(a_data);

    return 0;
}

#pragma endregion